using Microsoft.EntityFrameworkCore;
using ProcessManagementApi.DTOs;
using ProcessManagementApi.Services;
using MESData.ErrorCode;
using MESData.Infrastucture;
using MESBaseis.Domain.ZSH;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;

namespace ProcessManagementApi.Services
{
    /// <summary>
    /// 工序服务实现
    /// </summary>
    public class ProcessService : IProcessService 
    {
        private readonly MyDbcontext _context;

        public ProcessService(MyDbcontext context)
        {
            _context = context;
        }

        /// <summary>
        /// 分页查询工序
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <returns>分页结果</returns>
        public async Task<ApiPageing<ProcessResponseDto>> GetProcessesAsync(ProcessQueryDto query)
        {
            try
            {
                var queryable = _context.ZshProcesses
                    .Include(p => p.ProcessCategory)
                    .Where(p => !p.IsDeleted)
                    .AsQueryable();

                // 应用查询条件
                if (!string.IsNullOrEmpty(query.NumberOrName))
                {
                    queryable = queryable.Where(p =>
                        p.ProcessNumber.Contains(query.NumberOrName) ||
                        p.ProcessName.Contains(query.NumberOrName));
                }

                if (query.ProcessCategoryId.HasValue)
                {
                    queryable = queryable.Where(p => p.ProcessCategoryId == query.ProcessCategoryId.Value);
                }

                if (!string.IsNullOrEmpty(query.Department))
                {
                    queryable = queryable.Where(p => p.Department.Contains(query.Department));
                }

                if (!string.IsNullOrEmpty(query.ResponsiblePerson))
                {
                    queryable = queryable.Where(p => p.ResponsiblePerson.Contains(query.ResponsiblePerson));
                }

                if (query.IsActive.HasValue)
                {
                    queryable = queryable.Where(p => p.IsActive == query.IsActive.Value);
                }

                // 获取总数
                var totalCount = await queryable.CountAsync();

                // 分页查询
                var items = await queryable
                    .OrderByDescending(p => p.CreateTime)
                    .Skip((query.PageIndex - 1) * query.PageSize)
                    .Take(query.PageSize)
                    .Select(p => new ProcessResponseDto
                    {
                        Id = p.Id,
                        ProcessNumber = p.ProcessNumber,
                        ProcessName = p.ProcessName,
                        ProcessCategoryId = p.ProcessCategoryId,
                        ProcessCategoryName = p.ProcessCategory.ProcessCategoryName,
                        Department = p.Department,
                        ResponsiblePerson = p.ResponsiblePerson,
                        IsActive = p.IsActive,
                        Remarks = p.Remarks,
                        AttachmentFileName = p.AttachmentFileName,
                        CreatedBy = p.Creator,
                        CreatedTime = p.CreateTime,
                        UpdatedBy = p.Updator,
                        UpdatedTime = p.UpdateTime
                    })
                    .ToListAsync();

                var totalPages = (int)Math.Ceiling((double)totalCount / query.PageSize);

                return new ApiPageing<ProcessResponseDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "查询成功",
                    TotaCount = totalCount,
                    TotaPage = totalPages,
                    PageData = items
                };
            }
            catch (Exception ex)
            {
                return new ApiPageing<ProcessResponseDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"查询失败：{ex.Message}",
                    Data = null,
                    TotaCount = 0,
                    TotaPage = 0,
                    PageData = null
                };
            }
        }

        /// <summary>
        /// 根据ID获取工序详情
        /// </summary>
        /// <param name="id">工序ID</param>
        /// <returns>工序详情</returns>
        public async Task<ApiResult<ProcessResponseDto>> GetProcessByIdAsync(int id)
        {
            try
            {
                var process = await _context.ZshProcesses
                    .Include(p => p.ProcessCategory)
                    .Where(p => p.Id == id && !p.IsDeleted)
                    .Select(p => new ProcessResponseDto
                    {
                        Id = p.Id,
                        ProcessNumber = p.ProcessNumber,
                        ProcessName = p.ProcessName,
                        ProcessCategoryId = p.ProcessCategoryId,
                        ProcessCategoryName = p.ProcessCategory.ProcessCategoryName,
                        Department = p.Department,
                        ResponsiblePerson = p.ResponsiblePerson,
                        IsActive = p.IsActive,
                        Remarks = p.Remarks,
                        AttachmentFileName = p.AttachmentFileName,
                        CreatedBy = p.Creator,
                        CreatedTime = p.CreateTime,
                        UpdatedBy = p.Updator,
                        UpdatedTime = p.UpdateTime
                    })
                    .FirstOrDefaultAsync();

                if (process == null)
                {
                    return new ApiResult<ProcessResponseDto>
                    {
                        Code = ApiEnum.NotFound,
                        Msg = "工序不存在",
                        Data = null
                    };
                }

                return new ApiResult<ProcessResponseDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "查询成功",
                    Data = process
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<ProcessResponseDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"查询失败：{ex.Message}",
                    Data = null
                };
            }
        }

        /// <summary>
        /// 创建工序
        /// </summary>
        /// <param name="createDto">创建DTO</param>
        /// <returns>创建结果</returns>
        public async Task<ApiResult<ProcessResponseDto>> CreateProcessAsync(ProcessCreateDto createDto)
        {
            try
            {
                // 检查工序编号是否重复
                var existingNumber = await _context.ZshProcesses
                    .AnyAsync(p => p.ProcessNumber == createDto.ProcessNumber && !p.IsDeleted);

                if (existingNumber)
                {
                    return new ApiResult<ProcessResponseDto>
                    {
                        Code = ApiEnum.Error,
                        Msg = "工序编号已存在",
                        Data = null
                    };
                }

                // 检查工序分类是否存在
                var categoryExists = await _context.ZshProcessCategories
                    .AnyAsync(pc => pc.Id == createDto.ProcessCategoryId && !pc.IsDeleted);

                if (!categoryExists)
                {
                    return new ApiResult<ProcessResponseDto>
                    {
                        Code = ApiEnum.Error,
                        Msg = "指定的工序分类不存在",
                        Data = null
                    };
                }

                var process = new Process
                {
                    ProcessNumber = createDto.ProcessNumber,
                    ProcessName = createDto.ProcessName,
                    ProcessCategoryId = createDto.ProcessCategoryId,
                    Department = createDto.Department,
                    ResponsiblePerson = createDto.ResponsiblePerson,
                    IsActive = createDto.IsActive,
                    Remarks = createDto.Remarks,
                    CreateTime = DateTime.Now,
                    Creator = "System", // TODO: 从当前用户上下文获取
                    IsDeleted = false
                };

                _context.ZshProcesses.Add(process);
                await _context.SaveChangesAsync();

                var result = await GetProcessByIdAsync(process.Id);
                return new ApiResult<ProcessResponseDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "工序创建成功",
                    Data = result.Data
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<ProcessResponseDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"创建失败：{ex.Message}",
                    Data = null
                };
            }
        }

        /// <summary>
        /// 更新工序
        /// </summary>
        /// <param name="updateDto">更新DTO</param>
        /// <returns>更新结果</returns>
        public async Task<ApiResult<ProcessResponseDto>> UpdateProcessAsync(ProcessUpdateDto updateDto)
        {
            try
            {
                var process = await _context.ZshProcesses
                    .FirstOrDefaultAsync(p => p.Id == updateDto.Id && !p.IsDeleted);

                if (process == null)
                {
                    return new ApiResult<ProcessResponseDto>
                    {
                        Code = ApiEnum.NotFound,
                        Msg = "工序不存在",
                        Data = null
                    };
                }

                // 检查工序编号是否重复（排除当前记录）
                var existingNumber = await _context.ZshProcesses
                    .AnyAsync(p => p.ProcessNumber == updateDto.ProcessNumber && 
                                  p.Id != updateDto.Id && !p.IsDeleted);

                if (existingNumber)
                {
                    return new ApiResult<ProcessResponseDto>
                    {
                        Code = ApiEnum.Error,
                        Msg = "工序编号已存在",
                        Data = null
                    };
                }

                // 检查工序分类是否存在
                var categoryExists = await _context.ZshProcessCategories
                    .AnyAsync(pc => pc.Id == updateDto.ProcessCategoryId && !pc.IsDeleted);

                if (!categoryExists)
                {
                    return new ApiResult<ProcessResponseDto>
                    {
                        Code = ApiEnum.Error,
                        Msg = "指定的工序分类不存在",
                        Data = null
                    };
                }

                // 更新实体
                process.ProcessNumber = updateDto.ProcessNumber;
                process.ProcessName = updateDto.ProcessName;
                process.ProcessCategoryId = updateDto.ProcessCategoryId;
                process.Department = updateDto.Department;
                process.ResponsiblePerson = updateDto.ResponsiblePerson;
                process.IsActive = updateDto.IsActive;
                process.Remarks = updateDto.Remarks;
                process.UpdateTime = DateTime.Now;
                process.Updator = "System"; // TODO: 从当前用户上下文获取

                await _context.SaveChangesAsync();

                var result = await GetProcessByIdAsync(process.Id);
                return new ApiResult<ProcessResponseDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "工序更新成功",
                    Data = result.Data
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<ProcessResponseDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"更新失败：{ex.Message}",
                    Data = null
                };
            }
        }

        /// <summary>
        /// 删除工序
        /// </summary>
        /// <param name="id">工序ID</param>
        /// <returns>删除结果</returns>
        public async Task<ApiResult<bool>> DeleteProcessAsync(int id)
        {
            try
            {
                var process = await _context.ZshProcesses
                    .FirstOrDefaultAsync(p => p.Id == id && !p.IsDeleted);

                if (process == null)
                {
                    return new ApiResult<bool>
                    {
                        Code = ApiEnum.NotFound,
                        Msg = "工序不存在",
                        Data = false
                    };
                }

                // 检查是否被工艺流程使用
                var hasFlowSteps = await _context.ZshProcessFlowSteps
                    .AnyAsync(pfs => pfs.ProcessId == id && !pfs.IsDeleted);

                if (hasFlowSteps)
                {
                    return new ApiResult<bool>
                    {
                        Code = ApiEnum.Error,
                        Msg = "该工序已被工艺流程使用，无法删除",
                        Data = false
                    };
                }

                // 软删除
                process.IsDeleted = true;
                process.UpdateTime = DateTime.Now;
                process.Updator = "System"; // TODO: 从当前用户上下文获取

                await _context.SaveChangesAsync();

                return new ApiResult<bool>
                {
                    Code = ApiEnum.Success,
                    Msg = "工序删除成功",
                    Data = true
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<bool>
                {
                    Code = ApiEnum.Error,
                    Msg = $"删除失败：{ex.Message}",
                    Data = false
                };
            }
        }

        /// <summary>
        /// 批量删除工序
        /// </summary>
        /// <param name="ids">工序ID列表</param>
        /// <returns>删除结果</returns>
        public async Task<ApiResult<bool>> BatchDeleteProcessesAsync(List<int> ids)
        {
            try
            {
                if (ids == null || !ids.Any())
                {
                    return new ApiResult<bool>
                    {
                        Code = ApiEnum.Error,
                        Msg = "请选择要删除的工序",
                        Data = false
                    };
                }

                // 检查是否有工序被工艺流程使用
                var hasFlowSteps = await _context.ZshProcessFlowSteps
                    .AnyAsync(pfs => ids.Contains(pfs.ProcessId) && !pfs.IsDeleted);

                if (hasFlowSteps)
                {
                    return new ApiResult<bool>
                    {
                        Code = ApiEnum.Error,
                        Msg = "选中的工序中有已被工艺流程使用的，无法删除",
                        Data = false
                    };
                }

                // 获取要删除的工序
                var processes = await _context.ZshProcesses
                    .Where(p => ids.Contains(p.Id) && !p.IsDeleted)
                    .ToListAsync();

                if (!processes.Any())
                {
                    return new ApiResult<bool>
                    {
                        Code = ApiEnum.Error,
                        Msg = "未找到要删除的工序",
                        Data = false
                    };
                }

                // 批量软删除
                foreach (var process in processes)
                {
                    process.IsDeleted = true;
                    process.UpdateTime = DateTime.Now;
                    process.Updator = "System"; // TODO: 从当前用户上下文获取
                }

                await _context.SaveChangesAsync();

                return new ApiResult<bool>
                {
                    Code = ApiEnum.Success,
                    Msg = $"成功删除 {processes.Count} 个工序",
                    Data = true
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<bool>
                {
                    Code = ApiEnum.Error,
                    Msg = $"批量删除失败：{ex.Message}",
                    Data = false
                };
            }
        }

        /// <summary>
        /// 导出工序到Excel
        /// </summary>
        /// <param name="queryDto">查询条件</param>
        /// <returns>Excel文件字节数组</returns>
        public async Task<byte[]> ExportProcessesToExcelAsync(ProcessExportQueryDto queryDto)
        {
            var queryable = _context.ZshProcesses
                .Include(p => p.ProcessCategory)
                .Where(p => !p.IsDeleted)
                .AsQueryable();

            // 应用查询条件
            if (!string.IsNullOrEmpty(queryDto.NumberOrName))
            {
                queryable = queryable.Where(p =>
                    p.ProcessNumber.Contains(queryDto.NumberOrName) ||
                    p.ProcessName.Contains(queryDto.NumberOrName));
            }

            if (queryDto.ProcessCategoryId.HasValue)
            {
                queryable = queryable.Where(p => p.ProcessCategoryId == queryDto.ProcessCategoryId.Value);
            }

            if (!string.IsNullOrEmpty(queryDto.Department))
            {
                queryable = queryable.Where(p => p.Department.Contains(queryDto.Department));
            }

            if (!string.IsNullOrEmpty(queryDto.ResponsiblePerson))
            {
                queryable = queryable.Where(p => p.ResponsiblePerson.Contains(queryDto.ResponsiblePerson));
            }

            if (queryDto.IsActive.HasValue)
            {
                queryable = queryable.Where(p => p.IsActive == queryDto.IsActive.Value);
            }

            // 获取数据
            var processes = await queryable
                .OrderByDescending(p => p.CreateTime)
                .Select(p => new ProcessResponseDto
                {
                    Id = p.Id,
                    ProcessNumber = p.ProcessNumber,
                    ProcessName = p.ProcessName,
                    ProcessCategoryId = p.ProcessCategoryId,
                    ProcessCategoryName = p.ProcessCategory.ProcessCategoryName,
                    Department = p.Department,
                    ResponsiblePerson = p.ResponsiblePerson,
                    IsActive = p.IsActive,
                    Remarks = p.Remarks,
                    AttachmentFileName = p.AttachmentFileName,
                    CreatedBy = p.Creator,
                    CreatedTime = p.CreateTime,
                    UpdatedBy = p.Updator,
                    UpdatedTime = p.UpdateTime
                })
                .ToListAsync();

            // 创建Excel工作簿
            var workbook = new XSSFWorkbook();
            var sheet = workbook.CreateSheet("工序");

            // 创建标题样式
            var titleStyle = workbook.CreateCellStyle();
            var titleFont = workbook.CreateFont();
            titleFont.FontName = "微软雅黑";
            titleFont.FontHeightInPoints = 12;
            titleFont.IsBold = true;
            titleStyle.SetFont(titleFont);
            titleStyle.Alignment = HorizontalAlignment.Center;
            titleStyle.VerticalAlignment = VerticalAlignment.Center;
            titleStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
            titleStyle.FillPattern = FillPattern.SolidForeground;
            titleStyle.BorderBottom = BorderStyle.Thin;
            titleStyle.BorderLeft = BorderStyle.Thin;
            titleStyle.BorderRight = BorderStyle.Thin;
            titleStyle.BorderTop = BorderStyle.Thin;

            // 创建数据样式
            var dataStyle = workbook.CreateCellStyle();
            var dataFont = workbook.CreateFont();
            dataFont.FontName = "微软雅黑";
            dataFont.FontHeightInPoints = 11;
            dataStyle.SetFont(dataFont);
            dataStyle.Alignment = HorizontalAlignment.Left;
            dataStyle.VerticalAlignment = VerticalAlignment.Center;
            dataStyle.BorderBottom = BorderStyle.Thin;
            dataStyle.BorderLeft = BorderStyle.Thin;
            dataStyle.BorderRight = BorderStyle.Thin;
            dataStyle.BorderTop = BorderStyle.Thin;

            // 创建居中样式
            var centerStyle = workbook.CreateCellStyle();
            centerStyle.CloneStyleFrom(dataStyle);
            centerStyle.Alignment = HorizontalAlignment.Center;

            // 创建日期样式
            var dateStyle = workbook.CreateCellStyle();
            dateStyle.CloneStyleFrom(dataStyle);
            dateStyle.DataFormat = workbook.CreateDataFormat().GetFormat("yyyy-mm-dd hh:mm:ss");

            // 创建表头
            var headerRow = sheet.CreateRow(0);
            headerRow.Height = 500; // 设置行高

            var headers = new string[]
            {
                "序号", "工序编号", "工序名称", "工序分类", "部门", "负责人", "状态", "备注", "附件", "创建人", "创建时间", "更新人", "更新时间"
            };

            for (int i = 0; i < headers.Length; i++)
            {
                var cell = headerRow.CreateCell(i);
                cell.SetCellValue(headers[i]);
                cell.CellStyle = titleStyle;
            }

            // 填充数据
            for (int i = 0; i < processes.Count; i++)
            {
                var dataRow = sheet.CreateRow(i + 1);
                var process = processes[i];

                // 序号
                var cell0 = dataRow.CreateCell(0);
                cell0.SetCellValue(i + 1);
                cell0.CellStyle = centerStyle;

                // 工序编号
                var cell1 = dataRow.CreateCell(1);
                cell1.SetCellValue(process.ProcessNumber);
                cell1.CellStyle = dataStyle;

                // 工序名称
                var cell2 = dataRow.CreateCell(2);
                cell2.SetCellValue(process.ProcessName);
                cell2.CellStyle = dataStyle;

                // 工序分类
                var cell3 = dataRow.CreateCell(3);
                cell3.SetCellValue(process.ProcessCategoryName ?? "");
                cell3.CellStyle = dataStyle;

                // 部门
                var cell4 = dataRow.CreateCell(4);
                cell4.SetCellValue(process.Department ?? "");
                cell4.CellStyle = dataStyle;

                // 负责人
                var cell5 = dataRow.CreateCell(5);
                cell5.SetCellValue(process.ResponsiblePerson ?? "");
                cell5.CellStyle = dataStyle;

                // 状态
                var cell6 = dataRow.CreateCell(6);
                cell6.SetCellValue(process.IsActive ? "启用" : "禁用");
                cell6.CellStyle = centerStyle;

                // 备注
                var cell7 = dataRow.CreateCell(7);
                cell7.SetCellValue(process.Remarks ?? "");
                cell7.CellStyle = dataStyle;

                // 附件
                var cell8 = dataRow.CreateCell(8);
                cell8.SetCellValue(process.AttachmentFileName ?? "");
                cell8.CellStyle = dataStyle;

                // 创建人
                var cell9 = dataRow.CreateCell(9);
                cell9.SetCellValue(process.CreatedBy ?? "");
                cell9.CellStyle = dataStyle;

                // 创建时间
                var cell10 = dataRow.CreateCell(10);
                cell10.SetCellValue(process.CreatedTime);
                cell10.CellStyle = dateStyle;

                // 更新人
                var cell11 = dataRow.CreateCell(11);
                cell11.SetCellValue(process.UpdatedBy ?? "");
                cell11.CellStyle = dataStyle;

                // 更新时间
                var cell12 = dataRow.CreateCell(12);
                if (process.UpdatedTime.HasValue)
                {
                    cell12.SetCellValue(process.UpdatedTime.Value);
                    cell12.CellStyle = dateStyle;
                }
                else
                {
                    cell12.SetCellValue("");
                    cell12.CellStyle = dataStyle;
                }
            }

            // 自动调整列宽
            for (int i = 0; i < headers.Length; i++)
            {
                sheet.AutoSizeColumn(i);
                // 设置最小列宽，避免过窄
                if (sheet.GetColumnWidth(i) < 2000)
                {
                    sheet.SetColumnWidth(i, 2000);
                }
                // 设置最大列宽，避免过宽
                if (sheet.GetColumnWidth(i) > 8000)
                {
                    sheet.SetColumnWidth(i, 8000);
                }
            }

            // 转换为字节数组
            using var memoryStream = new MemoryStream();
            workbook.Write(memoryStream);
            return memoryStream.ToArray();
        }

        /// <summary>
        /// 检查工序编号是否存在
        /// </summary>
        /// <param name="processNumber">工序编号</param>
        /// <param name="excludeId">排除的ID</param>
        /// <returns>是否存在</returns>
        private async Task<bool> IsProcessNumberExistsAsync(string processNumber, int? excludeId = null)
        {
            var query = _context.ZshProcesses
                .Where(p => p.ProcessNumber == processNumber && !p.IsDeleted);

            if (excludeId.HasValue)
            {
                query = query.Where(p => p.Id != excludeId.Value);
            }

            return await query.AnyAsync();
        }

        /// <summary>
        /// 生成工序编码
        /// </summary>
        /// <returns>生成的工序编码</returns>
        public async Task<ApiResult<string>> GenerateProcessCodeAsync()
        {
            try
            {
                string prefix = "GX"; // 工序编码前缀
                string dateStr = DateTime.Now.ToString("yyyyMMdd"); // 日期部分
                
                // 查询今天已生成的最大序号
                string likePattern = $"{prefix}{dateStr}%";
                var maxNumber = await _context.ZshProcesses
                    .Where(p => p.ProcessNumber.StartsWith($"{prefix}{dateStr}") && !p.IsDeleted)
                    .Select(p => p.ProcessNumber)
                    .OrderByDescending(p => p)
                    .FirstOrDefaultAsync();

                int sequence = 1;
                if (!string.IsNullOrEmpty(maxNumber) && maxNumber.Length == 14) // GX + 8位日期 + 4位序号
                {
                    if (int.TryParse(maxNumber.Substring(10), out int maxSeq))
                    {
                        sequence = maxSeq + 1;
                    }
                }

                string processCode = $"{prefix}{dateStr}{sequence:D4}";
                
                // 确保编码不重复
                while (await IsProcessNumberExistsAsync(processCode))
                {
                    sequence++;
                    processCode = $"{prefix}{dateStr}{sequence:D4}";
                }

                return new ApiResult<string>
                {
                    Code = ApiEnum.Success,
                    Msg = "工序编码生成成功",
                    Data = processCode
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<string>
                {
                    Code = ApiEnum.Error,
                    Msg = $"生成工序编码失败：{ex.Message}",
                    Data = null
                };
            }
        }

    }
} 